package com.vogue.meeting.common.security.controller;

import cn.hutool.core.util.StrUtil;
import com.vogue.meeting.common.web.domain.Result;
import com.vogue.meeting.common.web.domain.ResultCode;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Oauth2 授权管理
 */
@Api(tags = {"Oauth2 授权管理"})
@Slf4j
@RestController
@RequestMapping("/api/oauth")
public class Oauth2Controller {
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private TokenEndpoint tokenEndpoint;
    @Autowired
    private CheckTokenEndpoint checkTokenEndpoint;
    /**
     * 1、获取access_token请求（/oauth/token）
     * 请求所需参数：client_id、client_secret、grant_type、username、password
     * postman header ==>>Authorization ：Basic YmlsbDpiaWxs 这是(client_id:client_secret)的Base64
     * postman header ==>>Content-Type ： application/json
     * grant_type=password：username、password必传
     * grant_type=wechat_mini：code（微信临时code）、userInfo(微信获取的)必传
     * grant_type=sms：smscode（短信验证码）、mobile必传
     *
     * {
     *     "grant_type": "password",
     *     "userName": "admin",
     *     "password": "123456",
     *     "client_id": "bill",
     *     "client_secret": "bill",
     *     "scope": "saas"
     * }
     *
     * 2、刷新token请求（/oauth/token）
     * 请求所需参数：grant_type、refresh_token、client_id、client_secret
     * 其中grant_type为固定值：grant_type=refresh_token
     * postman header ==>>Authorization ：Basic YmlsbDpiaWxs
     * postman header ==>>Content-Type ： application/json
     * postman body ==>>数据
     * {
     *     "grant_type":"refresh_token",
     *     "refresh_token": "9a40471ef68234936a5c1646969ead43",
     *     "client_id":"bill",
     *     "client_secret":"bill",
     *     "scope":"all"
     *     }
     *
     * 登陆返回携带其他附加信息：{@link com.vogue.meeting.common.security.config.AuthorizationServerConfigurer#configure(AuthorizationServerEndpointsConfigurer)}
     *
     * @param principal
     * @param parameters
     * @return
     * @throws HttpRequestMethodNotSupportedException
     */
    @PostMapping(value = "/token", produces = "application/json;charset=UTF-8")
    public Result getAccessToken(Principal principal, @RequestBody Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {

        DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) tokenEndpoint.getAccessToken(principal, parameters).getBody();

        //登陆返回携带其他附加信息
        Map<String, Object> additionalInformation = new LinkedHashMap(token.getAdditionalInformation());

        Map<String, Object> data = new HashMap<>();

        data.put("accessToken", token.getValue());

        if (token.getRefreshToken() != null) {
            data.put("refreshToken", token.getRefreshToken().getValue());
            data.put("expiration", token.getExpiration().getTime());//过期时间
        }
        //定制刷新token消息
        String grantType = parameters.get("grant_type");
        if (grantType.equals("refresh_token"))return Result.success(ResultCode.REFRESH_SUCCESS,data);

        return Result.success(ResultCode.LOGIN_SUCCESS,data);
    }
    /**
     * token校验
     * @param authHeader Authorization
     */
    @PostMapping(value = "/check", produces = "application/json;charset=UTF-8")
    public Result checkToken(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader) {
        if (StrUtil.isBlank(authHeader)) {
            return Result.success();
        }

        String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, StrUtil.EMPTY).trim();

        Map<String,Object> data = (Map<String, Object>) checkTokenEndpoint.checkToken(tokenValue);
        if ((Boolean) data.get("active")){

        }
        return Result.success(data);
    }
    /**
     * 退出并删除token
     * @param authHeader Authorization
     */
    @PostMapping(value = "/logout", produces = "application/json;charset=UTF-8")
    public Result logout(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader) {
        if (StrUtil.isBlank(authHeader)) {
            return Result.success();
        }
        String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, StrUtil.EMPTY).trim();
        OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
        if (accessToken == null || StrUtil.isBlank(accessToken.getValue())) {
            return Result.success();
        }
        // 清空 refresh token
        OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
        tokenStore.removeRefreshToken(refreshToken);
        // 清空access token
        tokenStore.removeAccessToken(accessToken);

        return Result.success(ResultCode.LOGOUT_SUCCESS);
    }


}
